<template>
  <div>
    <n-card :content-style="{paddingBottom: '0px',paddingTop: '17px'}">
      <n-space>
        <n-form label-placement="left">
          <n-form-item label="类别 :" size="small">
            <n-tag v-for="tag in sceneTags" v-model:checked="tag.checked" checkable @click="getCharacterInfoList" style="margin-left: 1px;">
              {{ tag.label }}
            </n-tag>
          </n-form-item>
          <n-form-item label="名称 :" size="small">
            <n-input v-model:value="queryForm.name" placeholder="请输入场景名称"></n-input>
          </n-form-item>

        </n-form>
      </n-space>
    </n-card>
    <n-card style="margin-top: 5px">
      <n-button type="primary" style="margin-bottom: 10px;"
                @click="resetForm() ;formTitle = '新增人物信息'; addModalShow = true">
        <template #icon>
          <n-icon>
            <AddSharp/>
          </n-icon>
        </template>
        新增
      </n-button>
      <n-scrollbar
          :content-style="{padding: '5px 5px 5px 5px', height: clientHeight - (layoutHeaderHeight  + tabsHeight + 225) + 'px'}">
        <n-grid x-gap="4" y-gap="4" :cols="5" item-responsive responsive="screen">
          <n-gi v-for="characterInfo in characterInfoList">
            <n-card :title="characterInfo.characterName">
              <template #header-extra>
                {{ characterInfo.characterGender}}
                <n-divider vertical />
                {{ characterInfo.characterAge}}
                <n-divider vertical/>
                <n-ellipsis style="width: 40px" v-if="characterInfo.characterNickname">
                  {{characterInfo.characterNickname }}
                </n-ellipsis>

              </template>
              <template #cover>
                <div>
                  <n-image style="max-height:  300px" object-fit="contain" v-if="characterInfo.characterAvatar"
                           :src="fileFunction.getCharacterInfoImage(characterInfo?.characterAvatar)">
                  </n-image>
                  <!--                  <img v-if="openPose?.poseExampleImage"-->
                  <!--                       :src="fileFunction.getOpenPoseImage(openPose?.poseExampleImage)" class="fg-image">-->
                </div>
              </template>
              <n-ellipsis>
                {{ characterInfo.characterDescription }}
              </n-ellipsis>
              <template #action>

                <n-space justify="end" v-if="props.mode === 'choseCharacterInfo'">
                  <n-button size="small" type="primary" @click="props.choseCharacter(characterInfo)">选择</n-button>
                </n-space>
                <n-space justify="space-between" v-else>
                  <n-button size="small" type="primary" @click="openSdPlugin(characterInfo)">生成图片</n-button>
                  <n-space>
                    <n-button size="small" type="info" :loading="deleteLoading"
                              @click="editForm(characterInfo)">修改
                    </n-button>
                    <n-button size="small" type="error" :loading="deleteLoading"
                              @click="deleteCharacterInfo(characterInfo)">删除
                    </n-button>
                  </n-space>

                </n-space>
              </template>
            </n-card>
          </n-gi>
        </n-grid>
      </n-scrollbar>
    </n-card>



    <n-drawer v-model:show="addModalShow" :width="800" :on-after-leave="getCharacterInfoList">

      <n-drawer-content :title="formTitle"  >
        <n-form
            ref="formRef"
            label-placement="left"
            :label-width="80"
        >
          <n-grid :cols="24">
            <n-form-item-gi :span="24" label="名称" path="characterName">
              <n-input v-model:value="characterForm.characterName" placeholder="人物名称"/>
            </n-form-item-gi>

            <n-form-item-gi :span="24" label="别名" path="characterName">
              <n-dynamic-tags v-model:value="characterForm.characterNicknames" />
            </n-form-item-gi>

            <n-form-item-gi :span="12" label="性别" path="characterGender">
              <n-select :options="sexDict" v-model:value="characterForm.characterGender" @update:value="sexSelect">
              </n-select>
            </n-form-item-gi>

            <n-form-item-gi :span="12" label="年龄段">
              <n-select :options="ageTypeOptions" v-model:value="characterForm.characterAge" @update:value="ageSelect" clearable></n-select>
            </n-form-item-gi>

            <n-form-item-gi :span="24" label="人物描述" path="characterDescription">
              <n-input :readonly="characterForm.resourceId" v-model:value="characterForm.characterDescription"
                       type="textarea" style="height: 100px;"
                       placeholder="人物性别,形象,衣着描述">
              </n-input>
              <n-button type="primary" style="height: 100px; margin-left: 5px;" @click="promptTemplateShow = true">
                提示词器
              </n-button>
            </n-form-item-gi>

            <n-form-item-gi :span="24" label=" " path="characterDescription">
              <n-card title="人物照片">
                <template #header-extra>
                  <n-space justify="end" v-if="characterForm.characterAvatar" @click="characterForm.characterAvatar = ''">
                    <n-button type="warning">清除</n-button>
                  </n-space>
                </template>
                <n-space justify="center">
                  <n-image
                      :style="{
                        width: canvasWidth + 'px',
                        height: canvasHeight + 'px'
                        }"
                      v-if="characterForm.characterAvatar && characterForm.characterAvatar.startsWith('data:image')"
                      :src="characterForm.characterAvatar"
                      alt=""
                      @load="handleImgLoad"/>
                  <n-image
                      :style="{
                        width: canvasWidth + 'px',
                        height: canvasHeight + 'px'
                      }"
                      v-if="characterForm.characterAvatar && !characterForm.characterAvatar.startsWith('data:image')"
                      :src="fileFunction.getCharacterInfoImage(characterForm.characterAvatar)"
                      alt=""
                      @load="handleImgLoad"/>
                </n-space>
                <n-empty description="未上传图片" v-if="!characterForm.characterAvatar">
                  <template #extra>
                    <n-upload
                        :custom-request="customRequest"
                        :accept="'image/*'"
                    >
                      <n-button>上传图片</n-button>
                    </n-upload>
                  </template>
                </n-empty>
              </n-card>
            </n-form-item-gi>


            <n-form-item-gi :span="24" label=" ">
              <n-alert type="warning" style="width: 100%">
                如您需要选择Lora,请先选择SD资源!
              </n-alert>
            </n-form-item-gi>

            <n-form-item-gi :span="24" label="LoRA" path="characterLora">
              <n-select v-model:value="characterForm.resourceId" :options="resourceOption">
              </n-select>
              <n-input v-model:value="characterForm.characterLora" placeholder="人物使用的LoRA" style="margin-left: 5px;">
              </n-input>
              <n-button :disabled="!characterForm.resourceId" type="primary" style="margin-left: 5px;"
                        @click="modelSelectorShow = true">模型选择
              </n-button>
            </n-form-item-gi>
            <n-form-item-gi :span="24" label="人物标签" path="characterLora">
              <n-select :options="characterTags" multiple v-model:value="characterForm.characterTags"></n-select>
            </n-form-item-gi>
          </n-grid>
        </n-form>
        <template #footer>

          <n-space justify="end">
            <n-button @click="addModalShow=false;getCharacterInfoList()">取消</n-button>
            <n-button type="primary" @click="submitForm" :loading="saveLoading">确定</n-button>
          </n-space>
        </template>
      </n-drawer-content>

    </n-drawer>



    <n-drawer v-model:show="modelSelectorShow" :width="promptTemplateWidth">
      <n-drawer-content title="Lora模型选择器" closable>
        <ModelSelector modelType="lora" :resourceId="characterForm.resourceId"
                       @modelSelectEvent="modelSelectEvent"></ModelSelector>
      </n-drawer-content>
    </n-drawer>

    <n-drawer v-model:show="promptTemplateShow" :width="promptTemplateWidth">
      <n-drawer-content title="提示词生成器" closable>
        <PromptTemplate code="03" @loadPromptEvent="loadPromptEvent"></PromptTemplate>
      </n-drawer-content>
    </n-drawer>


    <n-drawer v-model:show="detailDesignShow" :width="promptTemplateWidth" :close-on-esc="false">
      <n-drawer-content title="模型图片制作" :closable="true">
        <stableDiffusionPaint
            ref="stableDiffusionPaintRef"
            :defaultConfig="defaultConfig"
            from="character"
            :chosePic="chosePic"
        />
      </n-drawer-content>
    </n-drawer>
  </div>
</template>

<script lang="ts" setup>
import {h, nextTick, onMounted, ref} from 'vue'
import {NButton, NTag, UploadCustomRequestOptions} from "naive-ui";
import Bus from '@/components/file/box/GlobalUploader/utils/bus.js'
import {storeToRefs} from "pinia";
import {useSystemStore} from "@/store/modules/useSystemStore";
import {AddSharp} from "@vicons/ionicons5";
import fileFunction from '@/libs/globalFunction/file.js'
import {resourceController} from "@/api/resource/resourceController.api"
import {characterInfoController} from "@/api/controller/characterInfo/characterInfoController"
import PromptTemplate from "@/components/prompt/promptTemplate.vue"
import ModelSelector from "@/components/paint/modelSelector/modelSelector.vue"
import {useStaticDict} from "@/dictionary/useStaticDict"
import stableDiffusionPaint from '@/views/pages/aiart/stablediffusion/index.vue'
import {ttsDict} from "@/dictionary/ttsDict";

const promptTemplateWidth = ref(0)
const {
  clientHeight,
  layoutHeaderHeight,
  darkTheme,
  tabsHeight
} = storeToRefs(useSystemStore());
const characterInfoList = ref([])
// 性别字典
const sexDict = ref<Array<any>>([
  {
    label: "男性",
    value: "男性",
  },
  {
    label: "女性",
    value: "女性"
  }
])

const {ageTypeOptions} = ttsDict()
const addModalShow = ref(false)
const promptTemplateShow = ref(false)
const modelSelectorShow = ref(false)
const detailDesignShow = ref(false)
const resourceOption = ref([])
const queryForm = ref({
  tags: '',
  name: ''
})
// 设置canvas宽高
const canvasWidth = ref(300)
const canvasHeight = ref(300)


const formTitle = ref('新增人物信息')

const defaultConfig = ref({})

const stableDiffusionPaintRef = ref(null)

const sceneTags = ref([
  {
    label: '古风',
    checked: false,
    value: '古风'
  }, {
    label: '近代',
    checked: false,
    value: '近代'
  }, {
    label: '现代',
    checked: false,
    value: '现代'
  }, {
    label: '未来',
    checked: false,
    value: '未来'
  }
])


const characterForm = ref({
  id: '',
  characterName: '',
  characterNickname: '',
  characterDescription: '',
  characterLora: '',
  characterPersonality: '',
  characterAge: '',
  characterGender: '',
  characterAvatar: '',
  characterVoiceActor: '',
  characterTag: '',
  resourceId: '',
  characterTags: [],
  characterNicknames: []
})

const resetForm = () => {
  characterForm.value = {
    id: '',
    characterName: '',
    characterNickname: '',
    characterDescription: '',
    characterLora: '',
    characterPersonality: '',
    characterAge: '',
    characterGender: '',
    characterAvatar: '',
    characterVoiceActor: '',
    characterTag: '',
    resourceId: '',
    characterTags: [],
    characterNicknames: []
  }
}

const tableLoading = ref(false)
const deleteLoading = ref(false)
const saveLoading = ref(false)

const props = defineProps({
  mode: {
    type: String,
    default: 'characterEdit'
  },
  choseCharacter: {
    type: Function,
    default: () => {
    }
  }
})

const getSceneList = () => {
  tableLoading.value = true
  const tags: any = []
  sceneTags.value.forEach((tag: any) => {
    if (tag.checked) {
      tags.push(tag.value)
    }
  })
  queryForm.value.tags = tags.join(',')
  characterInfoController.getCharacterInfoList(queryForm.value).then((res) => {
    tableLoading.value = false
    if (res.code === 200) {
      characterInfoList.value = res.data
      characterInfoList.value.forEach((item: any) => {
        item.characterTags = item.characterTag.split(',')
        item.characterNicknames = item.characterNickname.split(',')
      })
    }
  }).finally(() => {
    tableLoading.value = false
  })

}


const handleImgLoad = (e: any) => {
  const image = e.target;
  let image_new = new Image()
  image_new.src = image.src
  image_new.onload = function () {
    // 计算图片宽高比例
    let imgRatio = image_new.width / image_new.height
    if (image_new.width > 400
        || image_new.height > 400) {
      // 计算缩放后的宽高
      if (imgRatio > 1) {
        canvasWidth.value = 400
        canvasHeight.value = image_new.height / (image_new.width / 400)
      } else {
        // 图片比较宽
        canvasWidth.value = image_new.width / (image_new.height / 400)
        canvasHeight.value = 400
      }
    } else {
      canvasWidth.value = image_new.width
      canvasHeight.value = image_new.height
    }
  }
}

const customRequest = (uploadOption: UploadCustomRequestOptions) => {
  const reader = new FileReader();
  //@ts-ignore
  reader.readAsDataURL(uploadOption.file.file);
  reader.onloadend = () => {
    let image = new Image()
    image.src = reader.result
    //@ts-ignore
    characterForm.value.characterAvatar = reader.result
  };
}
onMounted(() => {
  getSceneList()
  getResourceInfo()
  promptTemplateWidth.value = window.innerWidth - 300
  window.addEventListener('resize', handleResize);
})

// 窗口宽度变化
const handleResize = () => {
  promptTemplateWidth.value = window.innerWidth - 300;
}


const submitForm = () => {
  saveLoading.value = true
  characterForm.value.characterTag = characterForm.value.characterTags.join(',')
  characterForm.value.characterNickname = characterForm.value.characterNicknames.join(',')
  if(characterForm.value.characterAvatar && characterForm.value.characterAvatar.startsWith('data:image')){
    characterForm.value.characterAvatar = characterForm.value.characterAvatar.split(';base64,')[1]
  }
  characterInfoController.addCharacterInfo(characterForm.value).then((res) => {
    if (res.code === 200) {
      addModalShow.value = false
      getCharacterInfoList()
    }
  }).finally(() => {
    saveLoading.value = false
  })
}

/***
 * 获取绘画资源
 */
const getResourceInfo = () => {
  resourceController.getSDResource('SD').then(res => {
    if (res.code === 200) {
      res.data.forEach((item: any) => {
        // @ts-ignore
        resourceOption.value.push({
          label: item.resourceName,
          value: item.id
        })
      })
      console.log(resourceOption.value)
    }
  })
}

const deleteCharacterInfo = (row: any) => {
  window.$dialog.warning({
    title: "温馨提醒",
    content: "是否删除该人物模特",
    positiveText: "确定",
    negativeText: "取消",
    onPositiveClick: () => {
      deleteLoading.value = true
      characterInfoController.deleteCharacterInfo(row.id).then(res => {
        if (res.code === 200) {
          window.$message.success(res.msg)
          getCharacterInfoList()
        }
      }).finally(() => {
        deleteLoading.value = false
      })
    }
  })
}


const sexSelect = (key: any) => {
  characterForm.value.characterTags = []
  addTag()
}

const addTag = () => {
  if (characterForm.value.characterGender) {
    characterForm.value.characterTags.push(characterForm.value.characterGender)
  }
  if (characterForm.value.characterAge) {
    characterForm.value.characterTags.push(characterForm.value.characterAge)
  }
}

const ageSelect = (key: any) => {
  console.log(key)
  characterForm.value.characterTags = []
  addTag()
}

const modelSelectEvent = (modelObj: any) => {
  characterForm.value.characterLora = "<lora:" + modelObj.modelName + ":1>"
  modelSelectorShow.value = false
}


const loadPromptEvent = (prompt: string, negativePrompt: string) => {
  characterForm.value.characterDescription = prompt
  promptTemplateShow.value = false
}

const openSdPlugin = (characterInfo: any) => {
  defaultConfig.value = {
    "resourceId": "c602a2e2829137e0de0b0a443e4f0782",
    "defaultStyleId": "",
    "defaultPrompt": "(masterpiece:1 4, best quality),unity 8k wallpaper,ultra detailed,beautiful and aesthetic,perfect lighting,detailed background",
    "defaultNegativePrompt": "NSFW,paintings, sketches, lowres, normal quality, worst quality, low quality, cropped, dot, mole, ugly, grayscale, monochrome, duplicate, morbid, mutilated, missing fingers, extra fingers, too many fingers, fused fingers, mutated hands, bad hands, poorly drawn hands, poorly drawn face, poorly drawn eyebrows, bad anatomy, cloned face, long neck, extra legs, extra arms, missing arms missing legs, malformed limbs, deformed, simple background, bad proportions, disfigured, skin spots, skin blemishes, age spot, bad feet, error, text, extra digit, fewer digits, jpeg artifacts, signature, username, blurry, watermark, mask, logo",
    "defaultSeed": -1,
    "defaultSamplerName": "DPM++ 2M",
    "defaultBatchSize": 1,
    "defaultSteps": 20,
    "defaultWidth": 768,
    "defaultHeight": 576,
    "defaultRepaintTimes": 1,
    "defaultCfgScale": 7,
    "defaultModel": "toonyou_beta6.safetensors [e8d456c42e]",
    "defaultVae": "vae-ft-mse-840000-ema-pruned.safetensors",
    "sizeOption": "",
    "defaultClipSkip": 2,
    "defaultRestoreFaces": true,
    "defaultEnableHr": false,
    "defaultHrUpscaler": "R-ESRGAN 4x+",
    "defaultHrScale": 2,
    "defaultDenoisingStrength": 0.75,
    "defaultHrSecondPassSteps": 8,
    "defaultInterrogator": "wd14-vit-v2-git",
    "defaultRepaintModel": "img2img",
    "defaultResizeMode": "0",
    "defaultControlNet": {
      "input_image": "",
      "mask": "",
      "module": "tile_colorfix+sharp",
      "model": "control_v11f1e_sd15_tile_fp16 [3b860298]",
      "weight": 1,
      "resize_mode": 1,
      "lowvram": false,
      "processor_res": 0,
      "threshold_a": 8,
      "threshold_b": 0.35,
      "guidance": 1,
      "guidance_start": 0,
      "guidance_end": 1,
      "control_mode": 2,
      "pixel_perfect": true,
      "preProcessor": "Tile/Blur",
      "is_enable": false
    }
  };
  detailDesignShow.value = true
  characterForm.value = characterInfo
  nextTick(() => {
    const prompt = characterInfo.characterGender + ',' + characterInfo.characterDescription + ',' + characterInfo.characterLora
    stableDiffusionPaintRef.value.loadPrompt(prompt, null);
  })
}

const chosePic = (userFileId: string) => {
  // 更新
  characterForm.value.characterAvatar = userFileId
  const avatarDto = {
    id: characterForm.value.id,
    userFileId: userFileId
  }
  characterInfoController.saveAvatar(avatarDto).then((res) => {
    if (res.code === 200) {
      window.$message.success(res.msg)
      getCharacterInfoList()
    }
  }).finally(() => {
    detailDesignShow.value = false
  })

}

const editForm = (characterInfo:any) => {
  formTitle.value = '编辑人物信息'
  characterForm.value = characterInfo
  addModalShow.value = true
}
</script>

